---
title: "Python 文件操作"
categories:
- python
tags:
---

<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orgae883b5">计算相对路径</a>
<ul>
<li><a href="#orgc61654a">{% raw %} os.path.relpath(path, start=os.curdir) {% endraw %}</a></li>
</ul>
</li>
<li><a href="#org58d093e">获取Home目录</a></li>
<li><a href="#org715689a">mkdir</a>
<ul>
<li><a href="#orgc707989">{% raw %} os.mkdir(path, mode=0o777, *, dir_fd=None) {% endraw %}</a></li>
<li><a href="#org144e610">{% raw %} makedirs(name, mode=0o777, exist_ok=False) {% endraw %}</a></li>
</ul>
</li>
<li><a href="#org3794620">rm</a>
<ul>
<li><a href="#org24cf81a">{% raw %} os.remove(path, *, dir_fd=None) {% endraw %}</a></li>
</ul>
</li>
<li><a href="#org045f4cc">rmdir</a>
<ul>
<li><a href="#org46b5e0d">{% raw %} os.rmdir(path, *, dir_fd=None) {% endraw %}</a></li>
<li><a href="#org4213843">{% raw %} shutil.rmtree(path, ignore_errors=False, onerror=None) {% endraw %}</a></li>
</ul>
</li>
<li><a href="#org7172392">文件读写</a>
<ul>
<li><a href="#org9f85b1d">内置函数open，用于打开文件</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="outline-2" id="outline-container-orgae883b5">
<h2 id="orgae883b5">计算相对路径</h2>
<div class="outline-text-2" id="text-orgae883b5">
</div>
<div class="outline-3" id="outline-container-orgc61654a">
<h3 id="orgc61654a">{% raw %} os.path.relpath(path, start=os.curdir) {% endraw %}</h3>
<div class="outline-text-3" id="text-orgc61654a">
<p>
计算 start 到 path 的相对路径，这个函数只是计算，并没有访问文件系统，因此该路径不一定存在，这个函数也不会检查。
</p>
<dl class="org-dl">
<dt>{% raw %} start {% endraw %}</dt><dd>默认为当前路径：os.curdir</dd>
</dl>
<p>
例如，下面的 {% raw %} BASE_DIR=/home/gdme1320 {% endraw %} 路径后面是否带斜线，结果相同
</p>
<pre class="example">
os.path.relpath('/home/gdme1320/file.txt', BASE_DIR) 返回："file.txt"
os.path.relpath('/home/gdme1320', BASE_DIR) 返回： '.'
</pre>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org58d093e">
<h2 id="org58d093e">获取Home目录</h2>
<div class="outline-text-2" id="text-org58d093e">
<blockquote>
<p>
<a href="https://stackoverflow.com/questions/4028904/how-to-get-the-home-directory-in-python">https://stackoverflow.com/questions/4028904/how-to-get-the-home-directory-in-python</a>
</p>
</blockquote>
<div class="org-src-container">
<pre class="src src-python"><span style="font-weight: bold;">from</span> os.path <span style="font-weight: bold;">import</span> expanduser
<span style="font-weight: bold; font-style: italic;">home</span> = expanduser(<span style="font-style: italic;">"~"</span>)
os.path.expanduser(<span style="font-style: italic;">'~username'</span>) <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">获取其他用户的Home目录</span>
<span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">Python 3.5+</span>
<span style="font-weight: bold;">from</span> pathlib <span style="font-weight: bold;">import</span> Path
<span style="font-weight: bold; font-style: italic;">home</span> = <span style="font-weight: bold;">str</span>(Path.home())
</pre>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org715689a">
<h2 id="org715689a">mkdir</h2>
<div class="outline-text-2" id="text-org715689a">
</div>
<div class="outline-3" id="outline-container-orgc707989">
<h3 id="orgc707989">{% raw %} os.mkdir(path, mode=0o777, *, dir_fd=None) {% endraw %}</h3>
<div class="outline-text-3" id="text-orgc707989">
<p>
创建目录。如果目录已经存在则抛出FileExistsError异常。
</p>
<ul class="org-ul">
<li>{% raw %} mode {% endraw %}</li>
<li id="&lt;code&gt;dir_fd&lt;/code&gt;">3.3新增的参数，相对路径</li>
</ul>
<p>
在 {% raw %} tempfile {% endraw %} 模块下的 {% raw %} tempfile.mkdtemp() {% endraw %} 方法能够创建临时目录。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org144e610">
<h3 id="org144e610">{% raw %} makedirs(name, mode=0o777, exist_ok=False) {% endraw %}</h3>
<div class="outline-text-3" id="text-org144e610">
<p>
相当于 {% raw %} mkdir -p {% endraw %} 。
</p>
<dl class="org-dl">
<dt>{% raw %} exist_ok {% endraw %}</dt><dd>默认为False，当设置为False时，如果目录已经存在，则抛出OSError异常。</dd>
</dl>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org3794620">
<h2 id="org3794620">rm</h2>
<div class="outline-text-2" id="text-org3794620">
</div>
<div class="outline-3" id="outline-container-org24cf81a">
<h3 id="org24cf81a">{% raw %} os.remove(path, *, dir_fd=None) {% endraw %}</h3>
<div class="outline-text-3" id="text-org24cf81a">
<p>
删除文件。如果path是目录，则抛出OSError异常。
这个方法也支持相对路径（dir_fd）。
</p>
<p>
在windows上，删除一个正在使用的文件将引发异常，在unix上，只是文件计数器减一所以不会引发异常。
</p>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org045f4cc">
<h2 id="org045f4cc">rmdir</h2>
<div class="outline-text-2" id="text-org045f4cc">
</div>
<div class="outline-3" id="outline-container-org46b5e0d">
<h3 id="org46b5e0d">{% raw %} os.rmdir(path, *, dir_fd=None) {% endraw %}</h3>
<div class="outline-text-3" id="text-org46b5e0d">
<p>
删除目录，只有当目录为空的情况下能够使用此函数，否则将抛出OSError异常。
这个方法也支持相对路径（dir_fd）。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org4213843">
<h3 id="org4213843">{% raw %} shutil.rmtree(path, ignore_errors=False, onerror=None) {% endraw %}</h3>
<div class="outline-text-3" id="text-org4213843">
<p>
删除整个目录树
</p>
<ul class="org-ul">
<li>{% raw %} path {% endraw %} 必须指向一个目录，不能是目录的链接。</li>
<li id="&lt;code&gt;ignore_errors&lt;/code&gt;">如果设置为True则失败被忽略。否则，调用onerror处理，如果onerror没有指定则抛出异常。onerror有三个参数：
<dl class="org-dl">
<dt>{% raw %} function {% endraw %}</dt><dd>引发异常的函数</dd>
<dt>{% raw %} path {% endraw %}</dt><dd>目录</dd>
<dt>(no term)</dt><dd>{% raw %} sys.exc_info() {% endraw %} 返回的异常信息</dd>
</dl></li>
</ul>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org7172392">
<h2 id="org7172392">文件读写</h2>
<div class="outline-text-2" id="text-org7172392">
<ul class="org-ul">
<li>判断文件是否存在： {% raw %} os.path.isfile(fname) {% endraw %}</li>
<li>判断目录是否存在： {% raw %} os.path.isdir(dirname) {% endraw %}</li>
</ul>
</div>
<div class="outline-3" id="outline-container-org9f85b1d">
<h3 id="org9f85b1d">内置函数open，用于打开文件</h3>
<div class="outline-text-3" id="text-org9f85b1d">
<blockquote>
<p>
<a href="https://docs.python.org/3/library/functions.html#open">https://docs.python.org/3/library/functions.html#open</a>
</p>
</blockquote>
<p>
{% raw %} open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) {% endraw %}
</p>
<p>
打开文件，返回文件描述符。如果文件无法打开，则抛出OSError。
</p>
<dl class="org-dl">
<dt>file</dt><dd>path-like-object 指定路径（绝对或相对当前工作目录的路径）；
或者是一个已有的文件描述符（当closefd=True的时候，这个文件描述符随open函数返回的fd关闭而关闭。</dd>
<dt>mode</dt><dd><p>
字符串参数，以下模式的组合，默认是'r'，支持的mode有：
</p>
<ul class="org-ul">
<li>r  默认，以只读文本方式打开</li>
<li>w  写方式，如果文件存在，则原来文件的内容被删除</li>
<li>x  创建，如果文件已存在，则返回失败</li>
<li>a  写方式打开，如果文件已存在，则追加</li>
<li>b  二进制模式</li>
<li>t  默认，文本模式</li>
<li>+  读写方式</li>
</ul>
<p>
在二进制模式下，'w+b'模式会打开并并清空原文件，而'r+b'不会清空。
</p></dd>
<dt>buffering</dt><dd>integer 缓冲策略：
<ul class="org-ul">
<li>0: 无缓冲，仅限二进制模式</li>
<li>1: 行缓冲，仅限文本模式</li>
<li>&gt;1: 大于1的值表示使用指定的缓冲大小</li>
<li>当没有指定缓冲策略时：
<ul class="org-ul">
<li>二进制模式下，使用启发式尝试？（heuristic trying）判断底层设备的block size，从而计算出固定的缓冲大小。如果失败则使用io.DEFAULT_BUFFER_SIZE。在部分系统为4096或8192。</li>
<li>交互式文件（如terminal tty）使用行缓冲，其他文件使用上面的策略。</li>
</ul></li>
</ul></dd>
<dt>encoding</dt><dd>文本模式打开文件时使用的编码</dd>
<dt>errors</dt><dd>字符串，用于指定encode或decode失败时的行为，也就是仅限文本模式。值如下：
<dl class="org-dl">
<dt>strict</dt><dd>抛出ValueError，这个参数设置为None也是这种行为</dd>
<dt>ignore</dt><dd>忽略，这种行为会导致数据丢失</dd>
<dt>replace</dt><dd>无法解码编码的部分被替换为 '?'</dd>
<dt>surrogateescape</dt><dd>不识别的字节变成Unicode Private Use Area码点（U+DC80 ~ U+DCFF）。当回写数据的时候，这些码点又被转换成原来的字节。这种行为在处理未知编码的文件的时候很有用。</dd>
<dt>xmlcharrefreplace</dt><dd>仅写文件的时候能使用这种行为，未识别的字符被替换成XML character reference  &amp;#nnn</dd>
<dt>backslashreplace</dt><dd>使用Python的反斜线转义序列</dd>
<dt>namereplace</dt><dd>这种行为仅限写，未识别的字符被替换成 \N{...} 转义序列</dd>
</dl></dd>
<dt>newline</dt><dd><p>
仅限文本模式，定义 <a href="https://docs.python.org/3/glossary.html#term-universal-newlines">universal newlines mode</a> 工作的方式，值有： None, '', '\n', '\r', and '\r\n'。
</p>
<p>
读的时候，
</p>
<ul class="org-ul">
<li>当newline=None时，universal newlines mode开启，它将'\n', '\r', or '\r\n'作为行的结束符号，并且全部转换成 \n 返回给调用者。</li>
<li>newline=''时，使用上面的几个符号作为结尾，但不转换，而是直接返回给调用者。</li>
<li><p>
newline=其他符号时，使用指定的符作为行定界符，并且返回给调用者的时候不转换。
</p>
<p>
写的时候，
</p></li>
<li>如果newline=None，\n被替换成系统默认的行分隔符（os.linesep）；</li>
<li>if newline is '' or '\n'则没有替换；如果newline是其他的符号，则\n被替换成那个符号。</li>
</ul></dd>
<dt>closefd</dt><dd>当filename参数是fd时，fd是否随open函数返回的fd关闭而关闭。如果filename是文件名则closefd必须是True（默认值），否则抛出错误。</dd>
<dt>opener</dt><dd>自定义opener函数，该函数声明为 {% raw %} fd opener(file, flags) {% endraw %} 接受两个参数，并需要返回fd。
传递 {% raw %} os.open {% endraw %} 与传递None的效果是一样的</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
